package com.mazaiting.rtda.heap;

import cn.hutool.core.util.ObjectUtil;
import com.mazaiting.classfile.constant.ConstantFactory;
import com.mazaiting.classfile.constant.ConstantPool;
import com.mazaiting.classfile.constant.info.*;
import lombok.Getter;

import java.util.Arrays;

/**
 * 常量池
 *
 * @author mazaiting
 * @since 2021/8/16
 */
@Getter
public class MtConstantPool {
    /**
     * 类字节码
     */
    private final MtClass mtClass;
    /**
     * 常量数组
     */
    private final MtConstant[] constants;

    public MtConstantPool(MtClass mtClass, ConstantPool pool) {
        this.mtClass = mtClass;
        // 获取长度
        int count = pool.getCount();
        this.constants = new MtConstant[count];
        // 遍历赋值 从索引 1 的位置开始
        for (int i = 1; i < count; i++) {
            ConstantInfo constantInfo = pool.getConstantInfo(i);
            short tag = constantInfo.getTag();
            switch (tag) {
                case ConstantFactory.CONSTANT_INTEGER:
                    constants[i] = new MtConstant.MtIntConstant(tag, ((ConstantIntegerInfo) constantInfo).getValue());
                    break;
                case ConstantFactory.CONSTANT_FLOAT:
                    constants[i] = new MtConstant.MtFloatConstant(tag, ((ConstantFloatInfo) constantInfo).getValue());
                    break;
                case ConstantFactory.CONSTANT_LONG: // 在常量池中都是占据两个位置
                    constants[i] = new MtConstant.MtLongConstant(tag, ((ConstantLongInfo) constantInfo).getValue());
                    i++;
                    break;
                case ConstantFactory.CONSTANT_DOUBLE: // 在常量池中都是占据两个位置
                    constants[i] = new MtConstant.MtDoubleConstant(tag, ((ConstantDoubleInfo) constantInfo).getValue());
                    i++;
                    break;
                case ConstantFactory.CONSTANT_STRING:
                    constants[i] = new MtConstant.MtStringConstant(tag, ((ConstantStringInfo) constantInfo).string());
                    break;
                case ConstantFactory.CONSTANT_CLASS:
                    constants[i] = new MtConstant.MtClassRef(tag, this, ((ConstantClassInfo) constantInfo));
                    break;
                case ConstantFactory.CONSTANT_FIELD_REF:
                    constants[i] = new MtConstant.MtFieldRef(tag, this, ((ConstantFiledRefInfo) constantInfo));
                    break;
                case ConstantFactory.CONSTANT_METHOD_REF:
                    constants[i] = new MtConstant.MtMethodRef(tag, this, ((ConstantMethodRefInfo) constantInfo));
                    break;
                case ConstantFactory.CONSTANT_INTERFACE_METHOD_REF:
                    constants[i] = new MtConstant.MtInterfaceMethodRef(tag, this, ((ConstantInterfaceMethodRefInfo) constantInfo));
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 获取常量
     *
     * @param index 索引
     * @return 常量
     */
    public MtConstant getConstant(int index) {
        MtConstant constant = constants[index];
        if (ObjectUtil.isNotNull(constant)) {
            return constant;
        }
        throw new RuntimeException("No constants at index " + index);
    }

}


















